#pragma once
#include <boost/noncopyable.hpp>
#include "MouseCursorBackground.h"
#include "Rect.h"
#include "DirectDrawFwd.h"
#include "VideoObject.h"
#include "ClipRectangle.h"
#include "VideoSurfaceFwd.h"
#include "ImageFwd.h"
#include "Image.h"
#include "VideoSurfaceHandle.h"
#include "VideoSurface.h"
#include "ImportExport.h"

namespace ja2{ namespace sgp
{
	class Settings;

	//! Video manager.
	class VideoManager : boost::noncopyable
	{
		// Constants
	private:
		//! Maximum width of cursor.
		static short const MAX_CURSOR_WIDTH = 64;
		//! Maximum height of cursor.
		static short const MAX_CURSOR_HEIGHT = 64;
		
		// Enums
	public:
		//! Special video object handles given to blit function.
		enum SurfaceType
		{
			ST_PRIMARY = 0xFFFFFFF0,
			ST_BACK_BUFFER = 0xFFFFFFF1,
			ST_FRAME_BUFFER = 0xFFFFFFF2,
			ST_MOUSE_BUFFER = 0xFFFFFFF3
		};
	private:
		//! Buffer state.
		enum BufferState
		{
			BS_BUFFER_READY = 0x00,
			BS_BUFFER_BUSY = 0x01,
			BS_BUFFER_DIRTY = 0x02,
			BS_BUFFER_DISABLED = 0x03
		};
		//! Video state.
		enum VideoState
		{
			VS_OFF = 0x00,
			VS_ON = 0x01,
			VS_SHUTTING_DOWN = 0x02,
			VS_SUSPENDED = 0x04
		};

		// Typedefs
	private:
		//! Rect container.
		typedef std::vector<Rect> RectContainer_t;
		//! Direct draw pointer.
		typedef _com_ptr_t< _com_IIID<IDirectDraw, &IID_IDirectDraw> > IDirectDrawPtr;
		//! Map of surface clip rectangle.
		typedef std::map<std::uint_least32_t, ClipRectangle> ClipRectMap_t;

		// Attributes
	private:
		//! Screen width.
		std::uint_least16_t m_ScreenWidth;
		//! Screen height.
		std::uint_least16_t m_ScreenHeight;
		//! Pixel depth.
		std::uint_least8_t m_PixelDepth;
		//! Make sure we record the value of the hWindow (main window frame for the application).
		HWND m_hWnd;
		//! Direct Draw object.
		IDirectDrawPtr m_pDirectDrawObjectRef;
		//! Direct Draw object.
		IDirectDraw7Ptr m_pDirectDraw;
		//! Original mouse cursor.
		IDirectDrawSurfacePtr m_pMouseCursorOriginalDD;
		//! Mouse cursor backgrounds.
		MouseCursorBackgroundPtr_t m_pMouseCursorCurrent;
		MouseCursorBackgroundPtr_t m_pMouseCursorPrevious;
		//! Frame buffer state.
		BufferState m_FrameBufferState;
		//! Mouse buffer state.
		BufferState m_MouseBufferState;
		//! Video state.
		VideoState m_VideoState;
		//! Whole screen should be refreshed.
		bool m_ForceFullScreenRefresh;
		//! Dirty regions.
		RectContainer_t m_DirtyRegions;
		//! Settings.
		Settings const &m_Settings;
		//! Cursor store video object.
//		VideoObject m_CursorStore;
		//! Memory used for surfaces.
		std::uint_least32_t m_MemoryUsedForSurface;
		//! Primary surface.
		VideoSurfacePtr_t m_pPrimarySurface;
		//! Back buffer surface.
		VideoSurfacePtr_t m_pBackBufferSurface;
		//! Frame buffer surface.
		VideoSurfacePtr_t m_pFrameBufferSurface;
		//! Mouse buffer surface.
		VideoSurfacePtr_t m_pMouseBufferSurface;
		//! Clip rect map.
		ClipRectMap_t m_ClipRectMap;

		// Operations
	public:
		//! Invalidate whole screen.
		JA2_SGP_API void invalidate_screen();
		//! Refresh screen.
		JA2_SGP_API void refresh_screen();
		//! Get the one of main surfaces.
		JA2_SGP_API VideoSurface &get_main_surface(SurfaceType Type);
		//! Create video surface from image.
		JA2_SGP_API VideoSurfacePtr_t create_surface(ImagePtr_t const &pImage, VideoSurface::MemoryUsage Flags, Image::TransparencyBlitFlag TransparentFlag);
		//! Hide mouse cursor.
		/*!
			It is synonym for old SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR );
		*/
		JA2_SGP_API void hide_cursor();
	private:
		//! Clear surfaces.
		void delete_primary_video_surfaces();
		//! Create video surface from DD surface.
		static VideoSurfacePtr_t create_surface_from_dd_surface(IDirectDrawSurfacePtr pDDSurface);

		// Construction/Destruction
	public:
		JA2_SGP_API VideoManager(HWND hWnd, Settings &Settings_);
		JA2_SGP_API ~VideoManager();
	};
} /*sgp*/} /*ja2*/
